﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NHibernate;

namespace NhJump.Persistence.Batching
{
    /// <summary>
    /// Defers execution of criteria until enumeration begins 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class DeferredEnumeration<T> : IEnumerable<T>
    {
        private bool _resultHasBeenLoaded = false;
        private IList _result = null;
        private readonly IBatcher _batcher;

        /// <summary>
        /// Schedule a deferred List operation on criteria with batcher
        /// </summary>
        /// <param name="batcher"></param>
        /// <param name="criteria"></param>
        public DeferredEnumeration(IBatcher batcher, ICriteria criteria)
        {
            _batcher = batcher;

            _batcher.Add(criteria, result =>
                                   {
                                       _result = result;
                                       _resultHasBeenLoaded = true;
                                   });
        }

        /// <summary>
        /// Enumerate results of criteria.List()
        /// </summary>
        public IEnumerable<T> Enumerable
        {
            get
            {
                if (! _resultHasBeenLoaded)
                    _batcher.ExecuteAndClear();

                if (_result==null)
                    yield break;

                foreach (T item in _result)
                {
                    yield return item;
                }
            }
        }

        #region IEnumerable<T> Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable)Enumerable).GetEnumerator();
        }

        public IEnumerator<T> GetEnumerator()
        {
            return Enumerable.GetEnumerator();
        }

        #endregion return GetEnumerator();
    }
}

